//--------------------------------------------------------------------------------------
// File: Tutorial02.fx
//
// Copyright (c) Microsoft Corporation. All rights reserved.
//--------------------------------------------------------------------------------------
float4x4 Proj;
float4x4 View;
uint2 markedV;

struct VS_INPUT
{
    float3 pos : POSITION;
    float2 uv : TEXCOORD0;
    float3 normal : NORMAL;
    uint   index  : TEXCOORD1;
};

struct VS_OUT
{
    float4 Pos : SV_POSITION;
    float3 Posw : TEXCOORD0;
    float2 Tex	: TEXCOORD1;
    uint   index : TEXCOORD2;
};

struct PS_OUT
{
    float4 col : SV_Target0;
    uint2  index : SV_Target1;
};
//--------------------------------------------------------------------------------------
// Vertex Shader
//--------------------------------------------------------------------------------------
VS_OUT VS( VS_INPUT vIn)
{
    VS_OUT vOut;
    float4 v;
    v = mul(float4(vIn.pos, 1), View);
    vOut.Posw=v.xyz;
    vOut.Pos = mul(v, Proj);
    vOut.index = vIn.index;
    vOut.Tex = vIn.uv;
    return vOut;
}

//--------------------------------------------------------------------------------------
// Geometry Shader
//--------------------------------------------------------------------------------------
[maxvertexcount(9)]
void GS( triangle VS_OUT input[3], inout TriangleStream<VS_OUT> TriStream )
{
    VS_OUT vertices[3];
    VS_OUT center;
    VS_OUT midEdges[3];
    //
    // Calculate the face center
    //
    center.Posw = (input[0].Posw + input[1].Posw + input[2].Posw)/3.0;
    center.index = input[1].index;
    center.Pos = mul(float4(center.Posw,1), Proj);
    center.Tex = (input[0].Tex + input[1].Tex + input[2].Tex)/3.0;
    
    //
    // calc vertices
    //
    for( uint i=0; i<3; i++ )
    {
        vertices[i].Pos = input[i].Pos;
        vertices[i].Posw = input[i].Posw;
        vertices[i].index = input[i].index;
        vertices[i].Tex = input[i].Tex;
    }

    //
    // calc mid edges
    //
    for( uint i=0; i<3; i++ )
    {
        uint iNext = (i+1)%3; 
        midEdges[i].Posw = (input[i].Posw + input[iNext].Posw) * 0.5;
        midEdges[i].Pos = mul(float4(midEdges[i].Posw,1), Proj);
        midEdges[i].Tex = (input[i].Tex + input[iNext].Tex) * 0.5;
        midEdges[i].index = input[iNext].index;
    }
    
    //
    // output triangles
    //
    TriStream.Append(vertices[0]);
    TriStream.Append(midEdges[0]);
    TriStream.Append(center);
    TriStream.Append(vertices[1]);
    TriStream.Append(midEdges[1]);
    TriStream.Append(vertices[2]);
    center.index = input[0].index;
    TriStream.Append(center);
    TriStream.Append(midEdges[2]);
    TriStream.Append(vertices[0]);
    TriStream.RestartStrip();
}

//--------------------------------------------------------------------------------------
// Pixel Shader
//--------------------------------------------------------------------------------------
PS_OUT PS( VS_OUT pIn )
{
    PS_OUT pOut;
    if (markedV.x == pIn.index)
    {
        pOut.col = float4( 0.0f, 1.0f, 0.0f, 1.0f );    // Yellow, with Alpha = 1
    }
	else if (markedV.y == pIn.index)
	{
		pOut.col = float4( 1.0f, 0.0f, 0.0f, 1.0f );    // Yellow, with Alpha = 1
	}
    else
    {
        pOut.col = float4( 1.0f, 1.0f, 0.0f, 1.0f );    // Yellow, with Alpha = 1
    }
    pOut.index = uint2(pIn.index, 0);
    return pOut;
}

float4 VSPath(float3 pos : POSITION) : SV_POSITION
{
	 float4 ViewPos = mul(float4(pos, 1), View);
	 float4 PosH = mul(ViewPos, Proj);
	 return PosH;
}

float4 PSPath(float4 pos : SV_POSITION) : SV_TARGET0
{
	return float4(0, 0, 1, 1);
}

technique10 Terrain
{
    pass P0
    {
        SetVertexShader( CompileShader( vs_4_0, VS() ) );
        SetGeometryShader( CompileShader( gs_4_0, GS() ) );
        SetPixelShader( CompileShader( ps_4_0, PS() ) );
    }
}

technique10 RenderPath
{
	pass P0
	{
		 SetVertexShader( CompileShader( vs_4_0, VSPath() ) );
        SetGeometryShader( NULL );
        SetPixelShader( CompileShader( ps_4_0, PSPath() ) );
	}
}